#include <string>
#include <fstream>
#include <sstream>
#include <exception>
#include "GL/glew.h"
#include "ShaderUtil.h"

using std::exception;
using std::string;
using std::ifstream;
using std::stringstream;

static string readShaderSource(const string& file)
{
	stringstream ss;
	ifstream f(file);
	ss << f.rdbuf();
	return ss.str();
}

unsigned int initShader(const string& vFile, const string&  fFile)
{
	struct Shader {
		string       file;
		GLenum       type;
		string       source;
	} shaders[2] = {
		{ vFile, GL_VERTEX_SHADER, "" },
		{ fFile, GL_FRAGMENT_SHADER, "" }
	};

	GLuint program = glCreateProgram();

	for (int i = 0; i < 2; ++i) {
		Shader& s = shaders[i];
		s.source = readShaderSource(s.file);
		if (shaders[i].source.size() == 0) {
			throw exception("Failed to read shader file");
		}

		GLuint shader = glCreateShader(s.type);
		const GLchar *pSrc = static_cast<const GLchar*>(s.source.c_str());
		glShaderSource(shader, 1, &pSrc, NULL);
		glCompileShader( shader );

		GLint compiled;
		glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
		if (!compiled) {
			throw exception("Failed to compile shader");
			//GLint  logSize;
			//glGetShaderiv( shader, GL_INFO_LOG_LENGTH, &logSize );
			//char* logMsg = new char[logSize];
			//glGetShaderInfoLog( shader, logSize, NULL, logMsg );
			//delete [] logMsg;
		}

		glAttachShader(program, shader);
	}

	// link and error check
	glLinkProgram(program);

	GLint  linked;
	glGetProgramiv(program, GL_LINK_STATUS, &linked);
	if (!linked) {
		throw exception("Shader program failed to link");
		//GLint  logSize;
		//glGetProgramiv( program, GL_INFO_LOG_LENGTH, &logSize);
		//char* logMsg = new char[logSize];
		//glGetProgramInfoLog( program, logSize, NULL, logMsg );
		//delete [] logMsg;
	}

	// use program object
	glUseProgram(program);

	return program;
}
